/*REMLACER LES TESTERSYMCOUR PAR LS.GETSYMCOUR()="PARAM"*/

#include "LecteurPhraseSimple.h"
#include <stdlib.h>
#include <iostream>
using namespace std;

////////////////////////////////////////////////////////////////////////////////
LecteurPhraseSimple::LecteurPhraseSimple(string nomFich) : ls(nomFich) {}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::analyse() {
	programme();
	cout << "Syntaxe correcte." << endl;
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::programme() {
// <programme> ::= debut <seqInst> fin FIN_FICHIER
	sauterSymCour("debut");
	seqInst();
	sauterSymCour("fin");
	testerSymCour("<FINDEFICHIER>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::seqInst() {
// <seqInst> ::= <inst> ; { <inst> ; }
	do {
            inst(); sauterSymCour(";"); 
	} while (ls.getSymCour()=="<VARIABLE>" || ls.getSymCour()=="si" ||
                ls.getSymCour()=="tantque" || ls.getSymCour()=="repeter" ||
                ls.getSymCour()=="lire" || ls.getSymCour()=="ecrire");
	// tant que le symbole courant est un debut possible d'instruction...
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::inst() {
// <inst> ::= <affectation>
        if (ls.getSymCour()=="si") { instSi(); }
        else if (ls.getSymCour()=="tantque") { instTq(); }
        else if (ls.getSymCour()=="repeter") { instRepeter(); }
        else if (ls.getSymCour()=="lire") { instLire(); }
        else if (ls.getSymCour()=="ecrire") { instEcrire(); }
        else { affectation(); }
}

void LecteurPhraseSimple::instSi(){
// <instSi> ::= si ( <expBool> ) <seqInst> { sinonsi ( <expBool> ) <seqInst> } [ sinon <seqInst> ] finsi 
          sauterSymCour("si"); sauterSymCour("("); expBool(); sauterSymCour(")");
          seqInst();
          while (ls.getSymCour()=="sinonsi")
          {
              sauterSymCour("sinonsi"); sauterSymCour("("); expBool(); sauterSymCour(")");
              seqInst();
          }
          if (ls.getSymCour()=="sinon")
          {
              sauterSymCour("sinon");
              seqInst();
          }
        sauterSymCour("finsi");
}

void LecteurPhraseSimple::instTq(){
// <instTq> ::= tantque ( <expBool> ) <seqInst> fintantque
        sauterSymCour("tantque"); sauterSymCour("("); expBool(); sauterSymCour(")");
        seqInst();
        sauterSymCour("fintantque");
}

void LecteurPhraseSimple::instRepeter(){
// <instRepeter> ::= repeter <seqInst> jusqua ( <expBool> )
        sauterSymCour("repeter");
        seqInst();
        sauterSymCour("jusqua"); sauterSymCour("("); expBool(); sauterSymCour(")");
}

void LecteurPhraseSimple::instLire(){
// <instLire> ::= lire ( <variable> )
    sauterSymCour("lire"); sauterSymCour("(");
        if (ls.getSymCour()=="<VARIABLE>") { ls.suivant(); } else { erreur("<lire>"); }
        sauterSymCour(")");
}

void LecteurPhraseSimple::instEcrire(){
// <instEcrire> ::= ecrire ( <expression> | <chaine> )
    sauterSymCour("ecrire"); sauterSymCour("(");
        if (ls.getSymCour()=="<CHAINE>") { chaine(); }
        else { expression(); }
        sauterSymCour(")");
}
    
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::affectation() {
// <affectation> ::= <variable> = <expression>
    sauterSymCour("<VARIABLE>");
    sauterSymCour("=");
    expression();
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::expression() {
// <expression> ::= <terme> { <opBinaire> <terme> }
    if (ls.getSymCour()=="<VARIABLE>" || ls.getSymCour()=="<ENTIER>")
    {
	terme();
	while (ls.getSymCour()=="+" || ls.getSymCour()=="-") {
            opAdd();
            terme();
	}
    }
    else
        chaine();
}

void LecteurPhraseSimple::expBool() 
// <expBool> ::= <relation> { <opBool> <relation> }
{
    relation();
    while (ls.getSymCour()=="et" || ls.getSymCour()=="ou")
    {
        opBool();
        relation();
    }
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::chaine() {
//<chaine> ::= <chaine>
    if (ls.getSymCour()=="<CHAINE>")
        ls.suivant();
    else
        erreur("<chaine>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::facteur() {
// <facteur> ::= <entier>  |  <variable>  |  <opUnaire><expBool>  |  ( <expBool> )
    if (ls.getSymCour()=="<VARIABLE>" || ls.getSymCour()=="<ENTIER>"){
            ls.suivant();
    }
    else if (ls.getSymCour()=="-" || ls.getSymCour()=="non") {
            opUnaire();
            expBool();
    }
    else if (ls.getSymCour()=="(") {
            ls.suivant();
            expression();
            sauterSymCour(")");
    } else    
            erreur("<facteur>");
}

void LecteurPhraseSimple::terme()
// <terme> ::= <facteur> { <opMult> <facteur> }
{
    if (ls.getSymCour()=="<VARIABLE>" || ls.getSymCour()=="<ENTIER>")
    {
        facteur();
        while (ls.getSymCour()=="*" || ls.getSymCour()=="/")
        {
            opMult();
            facteur();            
        }
    }
    else
    {
        erreur("<terme>");
    }
}

void LecteurPhraseSimple::relation() 
 // <relation> ::= <expression> { <opRel> <expression> }
{
 expression();
 while (ls.getSymCour()=="==" || ls.getSymCour()=="!=" || ls.getSymCour()=="<=" 
         || ls.getSymCour()==">=" || ls.getSymCour()=="<" || ls.getSymCour()==">")
 {
     opRel();
     expression();
 }
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::opMult()
// <opBinaire> ::= + | - | *  | /
{
	if (ls.getSymCour()=="*" || ls.getSymCour()=="/")
		ls.suivant();
	else
		erreur("<opMult>");
}

void LecteurPhraseSimple::opAdd()
// <opBinaire> ::= + | - | *  | /
{
	if (ls.getSymCour()=="+" || ls.getSymCour()=="-")
		ls.suivant();
	else
		erreur("<opAdd>");
}

void LecteurPhraseSimple::opBool() 
// <opBool> ::= et | ou 
{
    if (ls.getSymCour()=="et" || ls.getSymCour()=="ou")
		ls.suivant();
	else
		erreur("<opBool>");
}
 
 void LecteurPhraseSimple::opRel()    
 // <opRel> ::= == | != | < | <= | > | >=
 {
     if (ls.getSymCour()=="==" || ls.getSymCour()=="!=" || ls.getSymCour()=="<=" 
             || ls.getSymCour()==">=" || ls.getSymCour()=="<" || ls.getSymCour()==">")
		ls.suivant();
	else
		erreur("<opRel>");
 }
 
 void LecteurPhraseSimple::opUnaire()   
 // <opUnaire> ::= - | non
 {
     if (ls.getSymCour()=="-" || ls.getSymCour()=="non")
         ls.suivant();
     else
         erreur("<opUnaire>");
 }
 
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::testerSymCour(string ch) {
	if (ls.getSymCour() != ch) {
		cout << endl << "-------- Erreur ligne " << ls.getLigne()
				<< " - Colonne " << ls.getColonne() << endl << "   Attendu : "
				<< ch << endl << "   Trouve  : " << ls.getSymCour() << endl
				<< endl;
		exit(0); // plus tard, on levera une exception
	}
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::sauterSymCour(string ch) {
	testerSymCour(ch);
	ls.suivant();
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseSimple::erreur(string mess) {
	cout << endl << "-------- Erreur ligne " << ls.getLigne() << " - Colonne "
			<< ls.getColonne() << endl << "   Attendu : " << mess << endl
			<< "   Trouve  : " << ls.getSymCour() << endl << endl;
	exit(0); // plus tard, on levera une exception
}
